package api

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/jiedan/student-web/server/model"
	"gorm.io/gorm"
)

// GradeHandler 成绩处理器
type GradeHandler struct {
	DB *gorm.DB
}

// NewGradeHandler 创建成绩处理器
func NewGradeHandler(db *gorm.DB) *GradeHandler {
	return &GradeHandler{DB: db}
}

// GetStudentGrades 获取学生所有成绩
func (h *GradeHandler) GetStudentGrades(c *gin.Context) {
	studentID, err := strconv.ParseUint(c.Param("student_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	// 检查学生是否存在
	var student model.Student
	result := h.DB.First(&student, studentID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 获取学生成绩
	type GradeWithCourse struct {
		model.Grade
		CourseName string  `json:"course_name"`
		CourseID   string  `json:"course_id"`
		Credits    float64 `json:"credits"`
		Semester   string  `json:"semester"`
	}

	var grades []GradeWithCourse
	result = h.DB.Table("grades").Select(
		"grades.*, courses.name as course_name, courses.course_id as course_id, courses.credits as credits, courses.semester as semester",
	).Joins(
		"left join courses on grades.course_id = courses.id",
	).Where(
		"grades.student_id = ?", studentID,
	).Scan(&grades)

	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get grades"})
		return
	}

	c.JSON(http.StatusOK, grades)
}

// GetCourseGrades 获取课程所有学生成绩
func (h *GradeHandler) GetCourseGrades(c *gin.Context) {
	courseID, err := strconv.ParseUint(c.Param("course_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid course ID"})
		return
	}

	// 检查课程是否存在
	var course model.Course
	result := h.DB.First(&course, courseID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Course not found"})
		return
	}

	// 获取课程成绩
	type GradeWithStudent struct {
		model.Grade
		StudentName string `json:"student_name"`
		StudentID   string `json:"student_id"`
		Class       string `json:"class"`
	}

	var grades []GradeWithStudent
	result = h.DB.Table("grades").Select(
		"grades.*, students.student_id as student_id, students.class as class, users.name as student_name",
	).Joins(
		"left join students on grades.student_id = students.id",
	).Joins(
		"left join users on students.user_id = users.id",
	).Where(
		"grades.course_id = ?", courseID,
	).Scan(&grades)

	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get grades"})
		return
	}

	c.JSON(http.StatusOK, grades)
}

// CreateGradeRequest 创建成绩请求
type CreateGradeRequest struct {
	StudentID uint    `json:"student_id" binding:"required"`
	CourseID  uint    `json:"course_id" binding:"required"`
	Score     float64 `json:"score" binding:"required"`
}

// CreateGrade 创建或更新成绩
func (h *GradeHandler) CreateGrade(c *gin.Context) {
	var req CreateGradeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 检查学生是否存在
	var student model.Student
	result := h.DB.First(&student, req.StudentID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 检查课程是否存在
	var course model.Course
	result = h.DB.First(&course, req.CourseID)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Course not found"})
		return
	}

	// 检查学生是否选了这门课
	var selection model.CourseSelection
	result = h.DB.Where("student_id = ? AND course_id = ?", req.StudentID, req.CourseID).First(&selection)
	if result.Error != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Student has not selected this course"})
		return
	}

	// 检查成绩是否已存在
	var existingGrade model.Grade
	result = h.DB.Where("student_id = ? AND course_id = ?", req.StudentID, req.CourseID).First(&existingGrade)

	if result.Error == nil {
		// 更新现有成绩
		existingGrade.Score = req.Score
		result = h.DB.Save(&existingGrade)
		if result.Error != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update grade"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"message": "Grade updated successfully"})
		return
	}

	// 创建新成绩
	grade := model.Grade{
		StudentID: req.StudentID,
		CourseID:  req.CourseID,
		Score:     req.Score,
	}

	result = h.DB.Create(&grade)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create grade"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"message": "Grade created successfully"})
}

// UpdateGradeRequest 更新成绩请求
type UpdateGradeRequest struct {
	Score float64 `json:"score" binding:"required"`
}

// UpdateGrade 更新成绩
func (h *GradeHandler) UpdateGrade(c *gin.Context) {
	studentID, err := strconv.ParseUint(c.Param("student_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	courseID, err := strconv.ParseUint(c.Param("course_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid course ID"})
		return
	}

	var req UpdateGradeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 检查成绩是否存在
	var grade model.Grade
	result := h.DB.Where("student_id = ? AND course_id = ?", studentID, courseID).First(&grade)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Grade not found"})
		return
	}

	// 更新成绩
	grade.Score = req.Score
	result = h.DB.Save(&grade)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update grade"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Grade updated successfully"})
}

// DeleteGrade 删除成绩
func (h *GradeHandler) DeleteGrade(c *gin.Context) {
	studentID, err := strconv.ParseUint(c.Param("student_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	courseID, err := strconv.ParseUint(c.Param("course_id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid course ID"})
		return
	}

	// 检查成绩是否存在
	var grade model.Grade
	result := h.DB.Where("student_id = ? AND course_id = ?", studentID, courseID).First(&grade)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Grade not found"})
		return
	}

	// 删除成绩
	result = h.DB.Delete(&grade)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete grade"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Grade deleted successfully"})
}